package com.example.financechain.service.Impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.example.financechain.Utils.GatewayUtilss;
import com.example.financechain.Utils.JsonData;
import com.example.financechain.Utils.UUIDUtils;
import com.example.financechain.Utils.UserThreadLocal;
import com.example.financechain.config.CacheKeyManager;
import com.example.financechain.domain.DTO.AuditBusiness;
import com.example.financechain.domain.entity.Business;
import com.example.financechain.domain.entity.Financing;
import com.example.financechain.domain.entity.Role;
import com.example.financechain.mapper.BusinessMapper;
import com.example.financechain.service.IBlockexploreService;
import com.example.financechain.service.IBusinessService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.hyperledger.fabric.gateway.*;
import org.hyperledger.fabric.sdk.Peer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;

import javax.jws.soap.SOAPBinding;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.cert.CertificateException;
import java.time.LocalDateTime;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeoutException;

/**
 * <p>
 * 订单信息表 服务实现类
 * </p>
 *
 * @author yy
 * @since 2023-04-22
 */
@Slf4j
@Service
public class BusinessServiceImpl extends ServiceImpl<BusinessMapper, Business> implements IBusinessService {

    @Autowired
    IBlockexploreService iBlockexploreService;

    @Autowired
    GatewayUtilss gatewayUtilss;

    @Override
    public JsonData createBusiness(Business business) {

        String start_name = UserThreadLocal.get().getRoleName();
        business.setStartName(start_name);

        String businessnum = CacheKeyManager.BS + UUIDUtils.getUUID(8);

        business.setBusinessnum(businessnum);
        business.setCreateTime(LocalDateTime.now());
        business.setStarttime(LocalDateTime.now().plusDays(1L));
        //设置为审核状态
        business.setStatus(0);
        boolean success = save(business);

        if(!success){
            return JsonData.buildError("创建业务失败");
        }

        return JsonData.buildSuccess(business,"业务办理成功");

    }

    @Override
    public JsonData querybusiness() {

        Role role = UserThreadLocal.get();

        LambdaQueryWrapper<Business> lambdaQueryWrapper =new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Business::getAcceptName,role.getRoleName());

        List<Business> businessList = list(lambdaQueryWrapper);

        return JsonData.buildSuccess(businessList,"业务列表");
    }


    @Override
    public JsonData queryStart() {

        Role role = UserThreadLocal.get();

        LambdaQueryWrapper<Business> lambdaQueryWrapper =new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Business::getStartName,role.getRoleName());

        List<Business> businessList = list(lambdaQueryWrapper);

        return JsonData.buildSuccess(businessList,"业务列表");


    }

    @Override
    public JsonData querybusinessbyId(Long id) {
        Business business = getById(id);

        return JsonData.buildSuccess(business);
    }

    @Override
    public JsonData auditBusiness(AuditBusiness auditBusiness) throws ContractException, CertificateException, IOException, InvalidKeyException, InterruptedException, TimeoutException {
        Integer status ;
        Role role = UserThreadLocal.get();

        //拿到业务
        Business business = getById(auditBusiness.getBusinessId());

        if(auditBusiness.getProgressStatus()==1){
            //状态改为驳回
            status = 2;

            UpdateWrapper<Business> updateWrapper =new UpdateWrapper<>();
            updateWrapper.lambda().eq(Business::getBusinessId,auditBusiness.getBusinessId()).set(Business::getStatus,status).set(Business::getRemark,auditBusiness.getResult());
            boolean success = update(updateWrapper);
            if (!success){
                return JsonData.buildSuccess(null,"状态更新失败");
            }

            return JsonData.buildSuccess(null,"已驳回");
        }else {
            status = 1;



            //上链 获取上链的交易ID
            String txid = hyperchain(business,role);



            UpdateWrapper<Business> updateWrapper =new UpdateWrapper<>();
            updateWrapper.lambda().eq(Business::getBusinessId,auditBusiness.getBusinessId()).set(Business::getStatus,status).set(Business::getTxid,txid).set(Business::getRemark,auditBusiness.getResult());

            boolean success = update(updateWrapper);
            if (!success){
                return JsonData.buildError("上链失败");
            }

            iBlockexploreService.updateBlockstore();

            return JsonData.buildSuccess(txid,"签约成功，产生区块");


        }



    }


    private String hyperchain(Business business,Role role) throws CertificateException, IOException, InvalidKeyException, ContractException, InterruptedException, TimeoutException {

        try (Gateway gateway = gatewayUtilss.build(role).connect()) {
            // Get the network and chaincode
            Network network = gateway.getNetwork("energycarchannel");
            Contract contract = network.getContract("businesscontract");

            // Set endorsement policy
            EnumSet<Peer.PeerRole> roles = EnumSet.of(Peer.PeerRole.ENDORSING_PEER);
            // ...

            // Submit transaction
            Transaction transaction = contract.createTransaction("RecordContract")
                    .setEndorsingPeers(network.getChannel().getPeers(EnumSet.of(Peer.PeerRole.ENDORSING_PEER)));
            transaction.submit(business.getBusinessnum(), business.getStartName(), business.getAcceptName(), LocalDateTime.now().toString(), business.getMaterialAddress());

            // Wait for transaction to complete and print transaction ID
            String txid = transaction.getTransactionId();

            log.info("++++++++++ txId:"+txid+"++++++++++++");
            //System.out.println("txId:" + txid);

            return txid;
        } catch (Exception e) {
            // Handle exceptions
            e.printStackTrace();
            return null;
        }
    }
}
